﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using XcoAppSpaces.Core;
using System.Diagnostics;
using System.Threading;

namespace AlternativePorts.Tests
{
	[TestFixture]
	//[Ignore]
	public class PerformanceTests
	{
		[Test]
		public void TestAlternativePort()
		{
			Stopwatch sw = new Stopwatch();

			int processed = 0;
			int num = 100000;
			var port = new Port<int>();
			var evt = new ManualResetEvent(false);
			port.RegisterReceiver(i =>
			{
				DoWork();
				Interlocked.Increment(ref processed);
				if (processed == num)
				{
					Console.WriteLine("Alternative Port Time: " + sw.Elapsed);
					evt.Set();
				}
			}, ReceiveMode.Parallel);

			sw.Start();
			foreach (var i in Enumerable.Range(0, num))
				port.Post(i);

			evt.WaitOne(20000);
			sw.Stop();
		}

		[Test]
		public void TestCcrPort()
		{
			Stopwatch sw = new Stopwatch();

			int processed = 0;
			int num = 100000;
			var evt = new ManualResetEvent(false);
			using (var space = new XcoAppSpace())
			{
				var port = space.Receive<int>(i =>
				{
					DoWork();
					Interlocked.Increment(ref processed);
					if (processed == num)
					{
						Console.WriteLine("Ccr Port Time: " + sw.Elapsed);
						evt.Set();
					}
				});

				sw.Start();
				foreach (var i in Enumerable.Range(0, num))
					port.Post(i);

				evt.WaitOne(20000);
			}
			sw.Stop();
		}

		[Test]
		public void TestSelfImplementedThreadPool()
		{
			Stopwatch sw = new Stopwatch();

			int processed = 0;
			int num = 100000;
			var evt = new ManualResetEvent(false);
			using (var tp = new AlternativePorts.Threading.ThreadPool(4))
			{
				sw.Start();
				foreach (var i in Enumerable.Range(0, num))
				{
					tp.EnqueueTask(new Threading.DelegateTask(() =>
					{
						DoWork();
						Interlocked.Increment(ref processed);
						if (processed == num)
						{
							Console.WriteLine("Self implemented Threadpool Time: " + sw.Elapsed);
							evt.Set();
						}
					}));
				}

				evt.WaitOne(20000);
			}
			sw.Stop();
		}

		private void DoWork()
		{
			foreach (var i in Enumerable.Range(1, 10000))
				Math.Sqrt(i);
		}
	}
}
